import { ref, reactive } from 'vue'
import { defineStore } from 'pinia'
import { useRouter, useRoute } from 'vue-router'
import { omit } from '@jcstdio/jc-utils'
import type { Ref } from 'vue'
import { store } from '@/stores'
import { removeElementFromArray } from '@/utils/array'
import { PAGE_TAB_INFORS, PAGE_TAB_CUNRUNT_INDEX } from '../enums'
import type { tabinfos, rawtabinfos } from '../types'
import { allTabsClosed, tabSelected } from '../event'

/**重新整理 index 属性 */
function _reindex(arr: tabinfos[]): tabinfos[] {
  const _ = arr.filter(Boolean)
  for (let index = 0; index < _.length; index++) {
    const item: tabinfos = _[index]
    item.index = index
  }
  return _
}

const _tabsStore = defineStore('dragtabs', () => {
  // 标签容器
  const tabs: Ref<tabinfos[]> = ref([])
  // 选中的标签
  const currentIndex = ref(NaN)
  /**
   * 设置新的被选中标签
   * @param index 新页面标签的索引值
   * @returns
   */
  function select(index: number): string | null {
    // 如果当前标签不为空
    if (tabs.value.length !== 0) {
      currentIndex.value = index
      localStorage.setItem(PAGE_TAB_CUNRUNT_INDEX, index.toString())
      const url = tabs.value[index].url
      tabSelected(index, url)
      return url
    }
    // 标签为空时，返回 null
    return null
  }

  /**
   * 打开一个新的标签，需要手动指定 index
   * @param tab 标签数据
   */
  function addTab(tab: tabinfos): void {
    tabs.value.push(tab)
    localStorage.setItem(PAGE_TAB_INFORS, JSON.stringify(tabs.value))
    currentIndex.value = tab.index
    localStorage.setItem(PAGE_TAB_CUNRUNT_INDEX, tab.index.toString())
  }

  /**
   * 打开一个新的标签，新标签添加到最后
   * @param tab
   */
  function appendTab(tab: rawtabinfos): void {
    tabs.value.push({ index: tabs.value.length, ...tab })
    localStorage.setItem(PAGE_TAB_INFORS, JSON.stringify(tabs.value))
    select(tabs.value.length - 1)
  }

  /**
   * 获取指定索引的标签信息
   * @param index 页面标签的索引
   */
  function getTab(index: number): tabinfos {
    return tabs.value[index]
  }

  /**
   * 关闭指定的标签
   * - 标签关闭时，当前如果标签正在使用，则需激活附近标签：
   *   - 如果下一个标签存在，则激活下一个标签；
   *   - 如果下一个标签不存在（这个是最后一个标签）：
   *     - 如果标签数大于1，则使用前一个标签；
   *     - 如果标签数等于1，则关闭前跳到初始页
   */
  function closeTab(index: number): void {
    // 依据索引移除标签后，对剩余标签做 index 属性排序
    tabs.value = _reindex(removeElementFromArray(tabs.value, index))
    const _len = tabs.value.length // 关闭后的标签总数
    // 当前如果关闭标签为激活标签
    if (index === currentIndex.value) {
      // 关闭标签后，有足够数量的标签则不改变index。相当于激活被关闭的后面一个标签
      if (_len > index) {
        select(index)
      }
      // 关闭后只有一个标签，则激活这个唯一标签
      else if (_len === 1) {
        select(0)
      }
      // 关闭标签后还有多个标签，但是标签总数不大于被关闭标签的索引号，则是关闭了最后一个标签。
      // 这时激活被关闭标签的前一个索引
      else if (index - 1 > 0) {
        select(index - 1)
      }
    }
    // 如果关闭的标签是当前激活的前一个标签
    else if (index < currentIndex.value) {
      // 为保持激活页面不变，标签多于1，则激活当前激活的前一个标签
      if (_len !== 1) {
        select(currentIndex.value - 1)
      }
      // 如果只有一个标签，则触发所有标签关闭事件
      else {
        allTabsClosed()
      }
    }
    localStorage.setItem(PAGE_TAB_INFORS, JSON.stringify(tabs.value))
  }

  /**关闭所有标签 */
  function closeAllTabs(): void {
    tabs.value.length = 0
    localStorage.setItem(PAGE_TAB_INFORS, '[]')
  }

  function _loadTab(tab: tabinfos): void {
    tabs.value.push(tab)
  }

  /**
   * 导入一组标签，一般用于初始化
   * @param arr
   */
  function reloadFrom(arr: (rawtabinfos | tabinfos)[]): void {
    for (let index = 0; index < arr.length; index++) {
      const element = arr[index]
      if (Object.keys(element).includes('index')) {
        _loadTab({ index: index, ...omit(element as tabinfos, 'index') })
      } else {
        _loadTab({ index: index, ...element })
      }
    }
  }

  return {
    tabs,
    currentIndex,
    addTab,
    appendTab,
    getTab,
    closeTab,
    closeAllTabs,
    reloadFrom,
    select
  }
})

export function useTabStore() {
  return _tabsStore(store)
}
